package com.hl.apilibrary;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.hl.apilibrary.cookie.CookiesManager;
import com.hl.apilibrary.util.HttpsUtil;
import com.hl.apilibrary.util.NetWorkUtils;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLSocketFactory;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class Api {
    //数据Gson格式化
    public static final int CONVERTER_TYPE_GSON = 0;
    //数据String格式化
    public static final int CONVERTER_TYPE_STRING = 1;
    //读超时长，单位：毫秒
    public static final int READ_TIME_OUT = 60000;
    //连接时长，单位：毫秒
    public static final int CONNECT_TIME_OUT = 60000;
    //设缓存有效期为两天
    private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;
    //请求的通用路径前缀
    private static final String baseUrl = "http://admin.ileadtek.com/public/index.php/api/";

    private Retrofit mRetrofit;
    private ApiService apiService;
    private static Api api = null;

    public Api(final Context context) {
        //开启Log
        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存
        File cacheFile = new File(context.getApplicationContext().getCacheDir(), "response");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
        //增加头部信息
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request build = chain.request().newBuilder()
                        .addHeader("Content-Type", "application/json;charset=utf-8")//text/html
                        .addHeader("Connection", "Keep-Alive")
//                        .addHeader("Accept", "application/json")
                        .addHeader("Accept", "*/*")
                        .addHeader("user-agent", "Android")
//                        .addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
                        .build();
                return chain.proceed(build);
            }
        };

        SSLSocketFactory sslSocketFactory = HttpsUtil.getSslSocketFactory(null, null, null);
        /**
         * 云端响应头拦截器，用来配置缓存策略
         * Dangerous interceptor that rewrites the server's cache-control header.
         *
         *     1. noCache 不使用缓存，全部走网络
         *
         *     2. noStore 不使用缓存，也不存储缓存
         *
         *     3. onlyIfCached 只使用缓存
         *
         *     4. maxAge 设置最大失效时间，失效则不使用 需要服务器配合
         *
         *     5. maxStale 设置最大失效时间，失效则不使用 需要服务器配合 感觉这两个类似 还没怎么弄清楚，清楚的同学欢迎留言
         *
         *     6. minFresh 设置有效时间，依旧如上
         *
         *     7. FORCE_NETWORK 只走网络
         *
         *     8. FORCE_CACHE 只走缓存
         */
        Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();
                HttpUrl originalHttpUrl = originalRequest.url();
                HttpUrl.Builder builder = originalHttpUrl.newBuilder();

                //可以在这里拦截请求，添加通用参数及加密等
                //EncodeParas(originalHttpUrl, builder);
                //addCommonParas(builder);

                HttpUrl url = builder.build();
                Request.Builder requestBuilder = originalRequest.newBuilder()
                        .url(url)
                        .method(originalRequest.method(), originalRequest.body());
                Request request = requestBuilder.build();

                if (!NetWorkUtils.isNetConnected(context.getApplicationContext())) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response originalResponse = chain.proceed(request);
                if (NetWorkUtils.isNetConnected(context.getApplicationContext())) {
                    //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                    String cacheControl = request.cacheControl().toString();
                    return originalResponse.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    return originalResponse.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC)
                            .removeHeader("Pragma")
                            .build();
                }
            }
        };

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)
                .addInterceptor(mRewriteCacheControlInterceptor)
                .addNetworkInterceptor(mRewriteCacheControlInterceptor)
                .addInterceptor(headerInterceptor)
                .addInterceptor(logInterceptor)
                .cache(cache)
                //cookie管理
                .cookieJar(new CookiesManager(context.getApplicationContext()))
                .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
                .sslSocketFactory(sslSocketFactory)
                .build();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .serializeNulls()
                .create();
        Retrofit.Builder builder
                = new Retrofit.Builder()
                .client(okHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create());

        builder.addConverterFactory(GsonConverterFactory.create(gson))
                .baseUrl(baseUrl);
        mRetrofit = builder.build();
        apiService = mRetrofit.create(ApiService.class);
    }

    public static ApiService getApiService(Context context) {
        if (api == null) {
            synchronized (Api.class) {
                if (api == null)
                    api = new Api(context);
            }
        }
        return api.apiService;
    }

    static class StringConverter implements Converter<ResponseBody, ResponseBody> {

        public static final StringConverter INSTANCE = new StringConverter();

        @Override
        public ResponseBody convert(ResponseBody value) throws IOException {
            return value;
        }
    }

    public static class StringConverterFactory extends Converter.Factory {
        public static final StringConverterFactory INSTANCE = new StringConverterFactory();

        public static StringConverterFactory create() {
            return INSTANCE;
        }

        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            if (type == String.class) {
                return StringConverter.INSTANCE;
            }
            return null;
        }

        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            return new Converter<String, RequestBody>() {
                @Override
                public RequestBody convert(String value) throws IOException {
                    return RequestBody.create(MediaType.parse("application/json;charset=utf-8"), value);
                }
            };
        }
    }
}
